package com.arvato.wxwork.service.staff;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.arvato.common.https.WxworkMiniproOwnRequestUtil;
import com.arvato.common.util.JsonUtil;
import com.arvato.minipro.bean.bean_dto.common.PageData;
import com.arvato.minipro.bean.bean_dto.common.Query;
import com.arvato.wxwork.bean.bean_do.staff.WxworkStaffInfoDo;
import com.arvato.wxwork.bean.bean_dto.WxworkStaffExtAttrDto;
import com.arvato.wxwork.bean.bean_dto.WxworkStaffInfoDto;
import com.arvato.wxwork.bean.bean_vo.staff.WxworkStaffInfoVo;
import com.arvato.wxwork.mapper.staff.WxworkStaffInfoMapper;
import com.arvato.wxwork.service.member.WxworkMemberBindService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;


@Service
@Transactional
public class WxworkStaffInfoService {
	
	@Autowired
	private WxworkStaffInfoMapper wxworkStaffInfoMapper;

	@Autowired
	private WxworkMiniproOwnRequestUtil wxworkMiniproOwnRequestUtil;
	
	@Autowired
	private WxworkMemberBindService wxworkMemberBindService;
	
	@Autowired
	private JsonUtil jsonUtil;
	/**
	 * 批量查询员工信息(分页)
	 * @param query
	 * @param pageNum
	 * @param pageSize
	 * @return
	 */
	public PageData listStaffByQuery(Query query, Integer pageNum, Integer pageSize){
		// 设置分页参数
		PageHelper.startPage(pageNum, pageSize);
		List<WxworkStaffInfoVo> staffList = wxworkStaffInfoMapper.listStaffByQuery(query);
		PageInfo<WxworkStaffInfoVo> pageInfo = new PageInfo<WxworkStaffInfoVo>(staffList);
		return new PageData(pageInfo.getTotal(), pageInfo.getList());
	}
	
	/**
	 * 批量查询员工信息(不分页)
	 * @param cardDo
	 * @return
	 */
	public List<WxworkStaffInfoVo> listStaffByQuery(Query query){
		return wxworkStaffInfoMapper.listStaffByQuery(query);
	}
	
	/**
	 * 查询一个员工详情
	 * @param staffId
	 * @return
	 */
	public WxworkStaffInfoVo getStaffById(String staffId) {
		return wxworkStaffInfoMapper.getStaffById(staffId);
	}
	
	/**
	 * 根据一个userid查询一个员工的详情
	 * @param staffId
	 * @return
	 */
	public WxworkStaffInfoVo getStaffByUserId(String userid) {
		List<WxworkStaffInfoVo> staffInfoList = wxworkStaffInfoMapper.getStaffByUserid(userid);
		if(staffInfoList.size() == 0) {
			return null;
		}
		return staffInfoList.get(0);
	}
	
	/**
	 * 查询远程的员工信息
	 * @param userid
	 * @return
	 */
	public WxworkStaffInfoDo getRemoteStaffInfo(String userid) {
		String accessToken = wxworkMiniproOwnRequestUtil.getMiniproAccessToken();
		if(accessToken == null) {
			throw new RuntimeException("获取token失败。");
		}
		// 根据userId调用微信的查询接口，查询用户的信息
		Map<String, Object> userInfoMap = wxworkMiniproOwnRequestUtil.getStaffInfoByUserId(userid, accessToken);
		if(!"0".equals(userInfoMap.get("errcode") + "")) {
			throw new RuntimeException("查询员工详情失败。" +  jsonUtil.obj2String(userInfoMap));
		}
		return staffInfoMapToDo(userInfoMap);
	}
	
	/**
	 * 新增一个员工到数据库
	 * @param staffInfoDo
	 */
	public int insert(WxworkStaffInfoDo staffInfoDo) {
		return wxworkStaffInfoMapper.insert(staffInfoDo);
	}
	
	/**
	 * 新增一个员工并且同步到腾讯
	 * @param staffInfoDo
	 * @throws Exception 
	 */
	public int insertAndUpload(WxworkStaffInfoDo staffInfoDo) throws Exception {
		int row = wxworkStaffInfoMapper.insert(staffInfoDo);
		if(row == 1) {
			// 插入成功之后，上传到腾讯云
			String accessToken = wxworkMiniproOwnRequestUtil.getMaillistAccessToken();
			if(accessToken == null) {
				throw new RuntimeException("获取accessToken失败");
			}
			Map<String, Object> resultMap = wxworkMiniproOwnRequestUtil.createStaff(staffInfoDo, accessToken);
			// 如果同步到腾讯不成功 就删除刚才的插入记录
			if(!"0".equals(resultMap.get("errcode") + "")) {
				// 扔出去RuntimeException才能回滚事务 上面的wxworkStaffInfoMapper.insert才会被回滚
				throw new RuntimeException("调用企业微信创建员工接口失败。" +  jsonUtil.obj2String(resultMap));
			}
		}
		return row;
	}
	
	/**
	 * 更新员工信息
	 * @param staffInfoDo
	 * @return
	 */
	public int update(WxworkStaffInfoDo staffInfoDo) {
		return wxworkStaffInfoMapper.update(staffInfoDo);

	}
	
	/**
	 * 修改一个员工并且同步到腾讯
	 * @param staffInfoDo
	 * @throws Exception 
	 */
	public int updateAndUpload(WxworkStaffInfoDo staffInfoDo) throws Exception {
		int row = wxworkStaffInfoMapper.update(staffInfoDo);
		if(row == 1) {
			// 修改成功之后，上传到腾讯云
			String accessToken = wxworkMiniproOwnRequestUtil.getMaillistAccessToken();
			if(accessToken == null) {
				throw new RuntimeException("获取accessToken失败");
			}
			WxworkStaffInfoDto staffDoToDto = staffDoToDto(staffInfoDo);
			Map<String, Object> resultMap = wxworkMiniproOwnRequestUtil.updateStaff(staffDoToDto, accessToken);
			// 如果同步到腾讯不成功 就删除刚才的修改记录
			if(!"0".equals(resultMap.get("errcode") + "")) {
				throw new RuntimeException("调用企业微信修改员工接口失败。" +  jsonUtil.obj2String(resultMap));
			}
		}
		return row;
	}
	
	
	/**
	 * 删除一个员工(本地线上的都删除)
	 * @param staffId
	 * @return
	 * @throws Exception 
	 */
	public int deleteLocalAndRemote(String staffId){
		WxworkStaffInfoVo staffVo = wxworkStaffInfoMapper.getStaffById(staffId);
		int row = wxworkStaffInfoMapper.delete(staffId);
		if(row == 1) {
			String accessToken = wxworkMiniproOwnRequestUtil.getMaillistAccessToken();
			if(accessToken == null) {
				throw new RuntimeException("获取accessToken失败");
			}
			// 删除员工在远程的信息
			Map<String, Object> resultMap = wxworkMiniproOwnRequestUtil.deleteStaff(staffVo.getUserid(), accessToken);
			String code = resultMap.get("errcode") + "";
			if(!"0".equals(code) && !"60111".equals(code)) {
				throw new RuntimeException("删除员工失败失败。" + jsonUtil.obj2String(resultMap));
			}
			// 同时删除这个员工的所有bc的绑定关系
			Query query = new Query();
			query.put("staffId", staffId);
			wxworkMemberBindService.deleteByQuery(query);
		}
		return row;
	}
	
	/**
	 * 根据userid 删除线上的一个员工
	 * @param userid
	 * @return
	 * @throws Exception 
	 */
	public int deleteRemote(String userid){
		String accessToken = wxworkMiniproOwnRequestUtil.getMaillistAccessToken();
		if(accessToken == null) {
			throw new RuntimeException("获取accessToken失败");
		}
		// 删除员工在远程的信息
		Map<String, Object> resultMap = wxworkMiniproOwnRequestUtil.deleteStaff(userid, accessToken);
		String code = resultMap.get("errcode") + "";
		if(!"0".equals(code) && !"60111".equals(code)) {
			throw new RuntimeException("删除员工失败失败。" + jsonUtil.obj2String(resultMap));
		}
		return 1;
	}
	
	/**
	 * 将员工离职
	 * @param staffId
	 * @return
	 * @throws Exception
	 */
	public int quit(String staffId) throws Exception {
		// 离职一个员工 将员工的状态设置为离职
		WxworkStaffInfoDo staffInfoDo = new WxworkStaffInfoDo();
		staffInfoDo.setStaffId(staffId);
		staffInfoDo.setStatus(3);
		int row = wxworkStaffInfoMapper.update(staffInfoDo);
		// 查出这个staff在腾讯的userid
		WxworkStaffInfoVo staffVo = wxworkStaffInfoMapper.getStaffById(staffId);
		if(row == 1) {
			String accessToken = wxworkMiniproOwnRequestUtil.getMaillistAccessToken();
			if(accessToken == null) {
				throw new RuntimeException("获取accessToken失败");
			}
			// 删除员工在远程的信息
			Map<String, Object> resultMap = wxworkMiniproOwnRequestUtil.deleteStaff(staffVo.getUserid(), accessToken);
			if(!"0".equals(resultMap.get("errcode") + "")) {
				throw new RuntimeException("离职员工失败失败。" + jsonUtil.obj2String(resultMap));
			}
		}
		return row;
	}
	
	/**
	 * 检查员工在本地库是否存在 如果存在 返回本地存在的对象
	 * @param staffCode
	 * @return
	 */
	public WxworkStaffInfoVo checkLocalStaffExist(String staffCode) {
		Query query = new Query();
		query.put("staffCode", staffCode);
		List<WxworkStaffInfoVo> list = wxworkStaffInfoMapper.checkStaffExist(query);
		if(list.size() >= 1) {
			return list.get(0);
		}
		return null;
	}
	
	/**
	 * 检查员工在线上是否存在 如果存在 返回此员工的userid
	 * 不存在 返回null
	 * @param staffCode
	 */
	@SuppressWarnings("unchecked")
	public String checkRemoteStaffExist(String staffCode) {
		String accessToken = wxworkMiniproOwnRequestUtil.getMaillistAccessToken();
		if(accessToken == null) {
			throw new RuntimeException("获取accessToken失败");
		}
		// 顶级部门的ID是1
		Map<String, Object> resultMap = wxworkMiniproOwnRequestUtil.getStaffListByDepartmentId(accessToken, 1);
		if(!"0".equals(resultMap.get("errcode") + "")) {
			throw new RuntimeException("获取部门下员工列表失败。" + jsonUtil.obj2String(resultMap));
		}
		List<Map<String, Object>> userList = (List<Map<String, Object>>)resultMap.get("userlist");
		for(Map<String, Object> userMap : userList) {
			Map<String, Object> extAttrMap = (Map<String, Object>)userMap.get("extattr");
			List<Map<String, Object>> attrList = (List<Map<String, Object>>)extAttrMap.get("attrs");
			for(Map<String, Object> attrDtoMap : attrList) {
				String name = attrDtoMap.get("name") + "";
				String value = attrDtoMap.get("value") + "";
				if("员工编号".equals(name) && staffCode.equals(value)) {
					return userMap.get("userid") + "";
				}
			}
		}
		return null;
	}

	/**
	 * 同步员工信息
	 */
	public int snycStaff() {
		List<WxworkStaffInfoVo> staffList = wxworkStaffInfoMapper.listStaffByQuery(null);
		for(WxworkStaffInfoVo staffInfoVo : staffList) {
			String userid = staffInfoVo.getUserid();
			if(userid == null || userid.equals("")) {
				continue;
			}
			try {
				WxworkStaffInfoDo staffInfoDo = getRemoteStaffInfo(userid);
				staffInfoDo.setStaffId(staffInfoVo.getStaffId());
				// 姓名以本地为准 不以腾讯的为准
				staffInfoDo.setName(null);
				wxworkStaffInfoMapper.update(staffInfoDo);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return staffList.size();
	}
	
	/**
	 * 员工通过二次验证之后 激活员工
	 * 激活成功返回userid
	 * @param code
	 */
	public String authSucc(String code) {
		// 首先获取token 
		String accessToken = wxworkMiniproOwnRequestUtil.getMaillistAccessToken();
		if(accessToken == null) {
			throw new RuntimeException("获取accessToken失败");
		}
		// 然后通过code 获取userid
		Map<String, Object> map = wxworkMiniproOwnRequestUtil.authCode(accessToken, code);
		if(!"0".equals(map.get("errcode") +"")) {
			throw new RuntimeException("认证code,换取userid失败" + jsonUtil.obj2String(map));
		}
		String userid = map.get("UserId") + "";
		Map<String, Object> resultMap = wxworkMiniproOwnRequestUtil.authSucc(accessToken, userid);
		if("0".equals(resultMap.get("errcode") + "")) {
			return 	userid;
		}
		return null;
	}

	/**
	 * 员工信息bean转换，do转json（一般调用企业微信的员工接口需要将员工信息转成json的时候需要调用）
	 * @param staffInfoDo
	 * @return
	 */
	private WxworkStaffInfoDto staffDoToDto(WxworkStaffInfoDo staffInfoDo) {
		WxworkStaffInfoDto staffDto = new WxworkStaffInfoDto();
		// 将wxworkStaffInfoDo中同属性的变量名的值复制到staffDto 我们给定的变量排除在外
		BeanUtils.copyProperties(staffInfoDo, staffDto, "isLeader", "enable", "alias", "department");
		// 具体部门的ID 需要看欧珀莱的企业微信后台上面的部门 
		staffDto.setIsLeader(0);
		if(staffInfoDo.getStatus() != null && staffInfoDo.getStatus() == 2) {
			staffDto.setEnable(0);
		}else {
			staffDto.setEnable(1);
		}
		staffDto.setAlias("");
		staffDto.setTo_invite(true);
		staffDto.setDepartment(departmentStrToList(staffInfoDo.getDepartment()));
		// 拼接员工的额外属性json
		Map<String, List<WxworkStaffExtAttrDto>> extattr = new HashMap<String, List<WxworkStaffExtAttrDto>>();
		List<WxworkStaffExtAttrDto> extAttrList = new ArrayList<WxworkStaffExtAttrDto>();
		extAttrList.add(new WxworkStaffExtAttrDto("所属门店", staffInfoDo.getStoreCode()));
		extAttrList.add(new WxworkStaffExtAttrDto("所属长", staffInfoDo.getLeaderName() + "-" + staffInfoDo.getLeaderCode()));
		extAttrList.add(new WxworkStaffExtAttrDto("员工编号", staffInfoDo.getStaffCode()));
		extattr.put("attrs", extAttrList);
		staffDto.setExtattr(extattr);
		return staffDto;
	}
	
	/**
	 * json转do
	 * @param userInfoMap
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private WxworkStaffInfoDo staffInfoMapToDo(Map<String, Object> userInfoMap) {
		WxworkStaffInfoDo staffInfoDo = new WxworkStaffInfoDo();
		staffInfoDo.setAvatar(userInfoMap.get("avatar") + "");
		staffInfoDo.setDepartment(userInfoMap.get("department") == null? "":userInfoMap.get("department").toString());
		staffInfoDo.setDepartmentOrder(userInfoMap.get("order") == null? "":userInfoMap.get("order").toString());
		staffInfoDo.setEmail(userInfoMap.get("email") == null? "":userInfoMap.get("email").toString());
		staffInfoDo.setEnable(Integer.valueOf(userInfoMap.get("enable") + ""));
		staffInfoDo.setEnglishName(userInfoMap.get("englishName") == null? "":userInfoMap.get("englishName").toString());
		String extAttr = userInfoMap.get("extattr") == null? "":userInfoMap.get("extattr").toString();
		staffInfoDo.setExtattr(extAttr);
		Map<String, Object> extAttrMap = (Map<String, Object>)userInfoMap.get("extattr");
		List<Map<String, Object>> attrList = (List<Map<String, Object>>)extAttrMap.get("attrs");
		for(Map<String, Object> map : attrList) {
			String name = map.get("name") + "";
			String value = map.get("value") + "";
			if("员工编号".equals(name)) {
				staffInfoDo.setStaffCode(value);
			}
			if("所属长".equals(name)) {
				if(value.split("-").length >= 2) {
					staffInfoDo.setLeaderName(value.split("-")[0]);
					staffInfoDo.setLeaderCode(value.split("-")[1]);
				}
			}
			if("所属门店".equals(name)) {
				staffInfoDo.setStoreCode(value);
			}
		}
		staffInfoDo.setExternalProfile(userInfoMap.get("external_profile") == null? "":userInfoMap.get("external_profile").toString());
		staffInfoDo.setGender(Integer.valueOf(userInfoMap.get("gender") + ""));
		staffInfoDo.setIsLeader(Integer.valueOf(userInfoMap.get("isleader") + ""));
		staffInfoDo.setMobile(userInfoMap.get("mobile") == null? "":userInfoMap.get("mobile").toString());
		staffInfoDo.setName(userInfoMap.get("name") == null? "":userInfoMap.get("name").toString());
		staffInfoDo.setPosition(userInfoMap.get("position") == null? "":userInfoMap.get("position").toString());
		staffInfoDo.setQrCode(userInfoMap.get("qr_code") == null? "":userInfoMap.get("qr_code").toString());
		staffInfoDo.setTelephone(userInfoMap.get("telephone") == null? "":userInfoMap.get("telephone").toString());
		staffInfoDo.setRemark("");
		return staffInfoDo;
	}
	
	/**
	 * 将部门的id字符串转成部门的id数组
	 * @param sourceStr
	 * @return
	 */
	private List<Integer> departmentStrToList(String sourceStr){
		List<Integer> list = new ArrayList<Integer>();
		sourceStr = sourceStr.replace("[", "").replace("]", "");
		for(String str : sourceStr.split(",")) {
			list.add(Integer.valueOf(str));
		}
		return list;
	}

	public String getOpenId(String userid) {
		// 首先获取token 
		String accessToken = wxworkMiniproOwnRequestUtil.getMaillistAccessToken();
		if(accessToken == null) {
			throw new RuntimeException("获取accessToken失败");
		}
		// 然后通过code 获取userid
		Map<String, Object> map = wxworkMiniproOwnRequestUtil.getOpenidByUserid(userid, accessToken);
		if(!"0".equals(map.get("errcode") +"")) {
			throw new RuntimeException("userid换取openid失败" + jsonUtil.obj2String(map));
		}
		String openid = map.get("openid") + "";
		return openid;
	}

}
